using System;
using System.Data;
using System.Linq;
using Magiq.Support;
using Magiq.Support.Database;

namespace Magiq.Support.Database {
    public abstract class QueryExecutor {
        protected const string TypeReferenceName = "__TypeReference__";
        private readonly bool addTypeReference;

        protected QueryExecutor(IDatabaseAdapter databaseAdapter, IQueryable where, bool addTypeReference) {
            this.addTypeReference = addTypeReference;
            DatabaseAdapter = databaseAdapter;
            Where = where;
        }

        protected PropertyMapping TypeReferenceProperty { get; private set; }
        protected IQueryable Where { get; private set; }
        protected IDatabaseAdapter DatabaseAdapter { get; private set; }
        protected IDbCommand Command { get; private set; }
        protected ITypeMapping Mapping { get; private set; }
        public string BaseTableName { get; private set; }

        public string BaseWhereClause {
            get { return Command.CommandText.From("\r\nFROM "); }
        }


        protected void SetCommand(IDbCommand command) {
            Command = command;
            BaseTableName = addTypeReference
                                ? Command.CommandText.From("SELECT").Until(".").Trim()
                                : Mapping.TableName;
        }

        public int ExecuteNonQuery(string sql) {
            Command.CommandText = sql;
            var ihaveToOpenTheConnection = Command.Connection.State != ConnectionState.Open;

            if (ihaveToOpenTheConnection)
                Command.Connection.Open();

            var result = Command.ExecuteNonQuery();

            if (ihaveToOpenTheConnection)
                Command.Connection.Close();
            return result;
        }

        protected virtual void Init(Type elementType) {
            Mapping =  DatabaseAdapter.GetMappingOf(elementType);
            TypeReferenceProperty = Mapping.Ids.First();
        }
    }
}